// DynamicMenu.h: interface for the CDynamicMenu class.
//
//////////////////////////////////////////////////////////////////////
#if !defined(AFX_DYNAMICMENU_H__6BD68023_E89C_4535_9AC2_532CD64DEC4B__INCLUDED_)
#define AFX_DYNAMICMENU_H__6BD68023_E89C_4535_9AC2_532CD64DEC4B__INCLUDED_



/**
	When a menu item is click, only its callback function would be called and without any other information
	So the callback function for the click action should parameter less.	
	How to Use:
		

	the class interface should be simple.
 */

#include <windows.h>
#define STL_USING_STRING
#define STL_USING_VECTOR
#include "stlhelper.h"


#if defined(_UNICODE) || defined(UNICODE)
#define std::wstring CSTRING;
#else
typedef std::string CSTRING;
#endif

template<class CallBackFunc>

class CDynamicMenu
{	
public:		
	
	struct MenuItem
	{
		CSTRING			m_text;
		UINT			m_ID;
		CallBackFunc	m_callpack;		
	};

	CDynamicMenu(HWND hParent): m_hParent(hParent)
	{
		m_hMenu = ::CreatePopupMenu();		
		m_itemindex = 0;
	}

	virtual ~CDynamicMenu()
	{
		::DestroyMenu(m_hMenu);
	}

	///show menu at mouse's pos
	void Show()
	{
		POINT pos;
		::GetCursorPos(&pos);
		int nSelection = ::TrackPopupMenu(m_hMenu,TPM_LEFTALIGN|TPM_LEFTBUTTON|TPM_VERTICAL|TPM_NONOTIFY|TPM_RETURNCMD,
			pos.x,pos.y,0,m_hParent,NULL);		
		
		(this->(m_items[nSelection-1].m_callpack))();
	
	}

	BOOL AddSeparator()
	{
		MENUITEMINFO mii= { 0 };
		mii.cbSize= sizeof(mii);
		mii.fMask= MIIM_TYPE | MIIM_ID;
		mii.fType= MFT_SEPARATOR;
	
		return ::InsertSeparator(m_hMenu,m_items.size(),TRUE,&mii);
	}

	BOOL InsertItem(LPCTSTR text, int pos,CallBackFunc func)
	{
		MENUITEMINFO mii = {0};
		mii.cbSize= sizeof(mii);
		mii.fMask= MIIM_TYPE | MIIM_ID;
		mii.fType= MF_STRING|MF_ENABLED;
		mii.dwTypeData = (LPSTR )text;
		mii.wID = m_itemindex++;
		
		::InsertMenuItem(m_hMenu,pos,TRUE,&mii);
		
		MenuItem info;
		info.m_callpack = func;
		info.m_text = text;
		
		m_items.push_back(info);
		
		return TRUE;
	}

	BOOL AppendItem(LPCTSTR text,CallBackFunc func)
	{
		return InsertItem(text,m_items.size(),func);
	}

	BOOL EnableItem(LPCTSTR item)
	{
	}

	bool LoadMenuConfig(TCHAR* fname)
	{
		return false;
	}




	
	int FindItemPos(LPCTSTR text)
	{
		for (unsigned i=0; i<m_items.size(); ++i)
		{
			if (m_items[i].m_text == text)
			{
				return i;
			}
		}

		return -1;
	}

	BOOL SetItemChecked(int pos)
	{
		MENUITEMINFO mii= {sizeof(mii), 0};
		SetMenuItemInfo(m_hMenu,pos,	TRUE,&mii);
	//	((::GetMenuState(m_hMenu, pos, MF_BYPOSITION) & flags)!=0);
	}

	//state check:
	BOOL IsItemChecked(int pos)
	{
		return this->CheckFlag(pos, MF_CHECKED);
	}


	BOOL IsItemDisabled(int pos)
	{
		return this->CheckFlag(pos, MF_DISABLED|MF_GRAYED);
	}

	BOOL IsSeparator(int pos)
	{
		MENUITEMINFO mii= {sizeof(mii), MIIM_TYPE, };
		::GetMenuItemInfo(m_hMenu, pos, TRUE, &mii);
		return mii.fType==MFT_SEPARATOR;
	}
protected:
// 	BOOL SetFlag(int id,int flags)
// 	{
// 		MENUITEMINFO mii = {sizeof(mii),MIIM_STATE,};
// 		GetMenuItemInfo(m_hMenu,id,TRUE,&mii);
// 		//mii.fState ~= flags;
// 		return mii.fState & flags != 0 ;		
// 	}
	BOOL CheckFlag(int id, int flags)
	{
		MENUITEMINFO mii = {sizeof(mii),MIIM_STATE,};
		GetMenuItemInfo(m_hMenu,id,TRUE,&mii);
		return mii.fState & flags != 0 ;		
	}
private:
	int   m_itemindex;
	HMENU m_hMenu;
	HWND m_hParent;
	std::vector<MenuItem> m_items;
};


#endif // !defined(AFX_DYNAMICMENU_H__6BD68023_E89C_4535_9AC2_532CD64DEC4B__INCLUDED_)
